package com.kepler.social.web.comp;

import com.kepler.social.common.constants.TipsConst;
import com.kepler.social.common.exception.GenericBusinessException;
import com.kepler.social.common.rule.SmsRule;
import com.kepler.social.common.utils.StringExtendsUtils;
import com.kepler.social.common.utils.ValidateAssert;
import com.kepler.social.domain.support.sms.SmsBo;
import com.kepler.social.domain.user.security.UserSecurityAggregate;
import com.kepler.social.domain.user.security.UserSecurityRepository;
import com.kepler.social.service.vo.LoginUser;
import com.kepler.social.service.vo.MobilePhoneVo;
import com.kepler.social.web.authentication.MobileAuthenticationToken;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.util.Objects;

@Component
public class SysLoginService {

    @Resource
    private SmsBo smsBo;
    @Resource
    private TokenService tokenService;
    @Resource
    private UserSecurityRepository userSecurityRepository;
    @Resource
    private AuthenticationManager authenticationManager;

    /**
     * 登录验证
     *
     * @param account  账号
     * @param password 密码
     * @return 结果
     */
    public String login(String account, String password, Long mobilePhoneNumber, Integer captcha) {
        if (StringUtils.isNoneBlank(account)) {
            return this.login(account, password);
        } else if (Objects.nonNull(mobilePhoneNumber)) {
            return this.login(mobilePhoneNumber, captcha);
        } else {
            throw new IllegalArgumentException(TipsConst.account_empty);
        }
    }

    public String login(String account, String password) {
        ValidateAssert.isTrue(StringUtils.isNoneBlank(account),
                TipsConst.account_empty);
        ValidateAssert.isTrue(StringExtendsUtils.isEmail(account) || StringExtendsUtils.isMobilePhoneNumber(account),
                TipsConst.incorrect_account_format);
        ValidateAssert.isTrue(StringUtils.isNotBlank(password), TipsConst.empty_password);
        Long userId ;
        if(StringExtendsUtils.isEmail(account)){
            UserSecurityAggregate aggregate = userSecurityRepository.findByEmail(account);
            aggregate.checkEmailInUse();
            userId = aggregate.getRoot().getUserId();
        } else {
            UserSecurityAggregate aggregate = userSecurityRepository.findByMobilePhone(Long.parseLong(account));
            aggregate.checkMobilePhoneInUse();
            userId = aggregate.getRoot().getUserId();
        }
        Authentication authentication;
        try {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(userId.toString(), password));
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                throw e;
            } else {
                throw new GenericBusinessException(e.getMessage(), e);
            }
        }
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 生成token
        return tokenService.createToken(loginUser);
    }

    public String login(Long mobilePhoneNumber, Integer captcha) {
        return login(SmsRule.defaultCcc(),  mobilePhoneNumber,  captcha);
    }

    public String login(Integer countryCallingCode, Long mobilePhoneNumber, Integer captcha) {
        ValidateAssert.isTrue(StringExtendsUtils.isMobilePhoneNumber(mobilePhoneNumber + ""),
                TipsConst.incorrect_mobile_phone_format);
        ValidateAssert.notNull(captcha, TipsConst.captcha_missing);
        smsBo.verifySmsCaptcha(SmsRule.defaultCcc(countryCallingCode), mobilePhoneNumber, captcha, false);
        Authentication authentication;
        try {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(
                    new MobileAuthenticationToken(
                            MobilePhoneVo.builder()
                                    .mobilePhoneNumber(mobilePhoneNumber)
                                    .countryCallingCode(countryCallingCode)
                                    .captcha(captcha)
                                    .build()
                    ));
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                throw e;
            } else {
                throw new GenericBusinessException(e.getMessage(), e);
            }
        }
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 生成token
        return tokenService.createToken(loginUser);
    }
}